import aio_pika
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from loguru import _Logger
from peewee import Proxy
from peewee_async import Manager
from aioredis import Redis
from elasticsearch import AsyncElasticsearch

from common.config.settings import Settings
from common.initialize.init_logger import init_logger as _init_logger
from common.initialize.init_settings import init_settings as _init_settings
from common.initialize.init_mgw import init_db as _init_db
from common.initialize.init_redis import init_redis as _init_redis
from common.initialize.init_apscheduler import init_scheduler as _init_scheduler
from common.initialize.init_bloomfilter import init_tenant_bloomfilter as _init_tenant_bloomfilter
from common.initialize.init_bloomfilter import init_email_bloomfilter as _init_email_bloomfilter
from common.initialize.init_bloomfilter import init_mall_bloom_filter as _init_mall_bloom_filter
from common.initialize.init_id_worker import init_id_worker as _init_id_worker
from common.initialize.init_id_worker import close_id_worker as _close_id_worker
from common.initialize.init_rabbitmq import init_rabbitmq_client_pool as _init_rabbitmq_client_pool
from common.initialize.init_es_client import (
    init_spu_es_client as _init_spu_es_client,
    init_es_client as _init_es_client
)

from common.pkg.req import Client, init_client as _init_client
from common.pkg.bloom_filter_util import SimpleBloomFilter
from common.pkg.str_id import IdWorker
from common.pkg.es_util import SPUESClient


DB_PROXY = Proxy()
G_LOGGER: _Logger
G_SETTINGS: Settings
G_MGW: Manager
G_REDIS: Redis
G_SCHEDULER: AsyncIOScheduler
G_CLIENT:Client
G_TENANT_BLOOMFILTER: SimpleBloomFilter
G_TENANT_EMAIL_BLOOMFILTER: SimpleBloomFilter
G_MALL_BLOOMFILTER: SimpleBloomFilter
G_ID_WORKER: IdWorker
G_MQ: aio_pika.pool.Pool
G_ES_CLIENT: AsyncElasticsearch
G_SPU_ES_CLIENT: SPUESClient

def init_settings():
    global G_SETTINGS
    G_SETTINGS = _init_settings()
    return G_SETTINGS


def init_logger():
    global G_LOGGER
    G_LOGGER = _init_logger(G_SETTINGS)
    return G_LOGGER


def init_db(loop):
    global G_MGW
    G_MGW = _init_db(loop, db_config=G_SETTINGS.mysql_config)
    return G_MGW


async def close_db():
    global G_MGW
    await G_MGW.close()


def init_redis():
    global G_REDIS
    G_REDIS = _init_redis(G_SETTINGS.redis_config)
    return G_REDIS


async def close_redis():
    global G_REDIS
    await G_REDIS.close()


def init_apscheduler():
    global G_SCHEDULER
    G_SCHEDULER = _init_scheduler(G_SETTINGS.apscheduler_redis_config)
    return G_SCHEDULER


async def init_client(loop):
    global G_CLIENT
    G_CLIENT = await _init_client(loop)
    return G_CLIENT


def init_tenant_bloomfilter():
    global G_TENANT_BLOOMFILTER
    G_TENANT_BLOOMFILTER = _init_tenant_bloomfilter()
    return G_TENANT_BLOOMFILTER


def init_tenant_email_bloomfilter():
    global G_TENANT_EMAIL_BLOOMFILTER
    G_TENANT_EMAIL_BLOOMFILTER = _init_email_bloomfilter()
    return G_TENANT_EMAIL_BLOOMFILTER


def init_mall_bloomfilter():
    global G_MALL_BLOOMFILTER
    G_MALL_BLOOMFILTER = _init_mall_bloom_filter()
    return G_MALL_BLOOMFILTER


async def init_id_worker(settings):
    global G_ID_WORKER
    count = 3
    while count > 0:
        try:
            id_worker = await _init_id_worker(settings)
            if id_worker:
                G_ID_WORKER = id_worker
                return G_ID_WORKER
            else:
                count -= 1
        except RuntimeError:
            count -= 1
    raise RuntimeError("初始化id worker失败 机器用光")


async def init_rabbitmq_client_pool(lp, config):
    global G_MQ
    G_MQ = await _init_rabbitmq_client_pool(lp, config)
    return G_MQ


def init_es_client(es_config):
    global G_ES_CLIENT
    G_ES_CLIENT = _init_es_client(es_config)
    return G_ES_CLIENT


def init_spu_es_client(es_client):
    global G_SPU_ES_CLIENT
    G_SPU_ES_CLIENT = _init_spu_es_client(es_client)
    return G_SPU_ES_CLIENT


async def close_client():
    global G_CLIENT
    await G_CLIENT.close()


async def clear_id_worker_status():
    global G_ID_WORKER
    await _close_id_worker(G_ID_WORKER)


async def close_rabbitmq_client_pool():
    global G_MQ
    await G_MQ.close()

